#pragma once
#include "requestor.hpp"
#include <future>
#include <jsoncpp/json/value.h>
#include <memory>

namespace rpc
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallBack = std::function<void(const Json::Value&)>;
            RpcCaller(const Requestor::ptr requestor):_requestor(requestor)
            {}

            //requestor的处理是针对BaseMessage
            //该模块针对的是RpcResponse中的result处理的
            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, Json::Value &result)
            {
                //组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMethod(method);
                req_msg->setParams(params);
                req_msg->setMtype(MType::REQ_RPC);
                //发送请求
                BaseMessage::ptr rsp_msg;
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<RpcRequest>(req_msg), rsp_msg);
                if(!ret)
                {
                    ELOG("同步rpc请求失败");
                    return false;
                }
                //等待响应
                auto rpc_rsp_msg  = std::dynamic_pointer_cast<RPCResponse>(rsp_msg);
                if(!rpc_rsp_msg)
                {
                    ELOG("rpc响应，向下类型转换失败");
                    return false;
                }
                if(rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    std::string err_msg = errReason(rpc_rsp_msg->rcode());
                    ELOG("rpc请求出错: %s", err_msg.c_str());
                    return false;
                }
                result = rpc_rsp_msg->result();
                return true;
            }
            
            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, std::future<Json::Value> &result)
            {
                //组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMethod(method);
                req_msg->setParams(params);
                req_msg->setMtype(MType::REQ_RPC);

                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallback cb = std::bind(&RpcCaller::CallBack, this, json_promise, std::placeholders::_1); 
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), cb);
                if(!ret)
                {
                    ELOG("异步rpc请求失败！");
                    return false;
                }
                return true;
            }
            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, const JsonResponseCallBack &cb)
            {
                //组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMethod(method);
                req_msg->setParams(params);
                req_msg->setMtype(MType::REQ_RPC);

                Requestor::RequestCallback callback = std::bind(&RpcCaller::CallBackSync, this, cb, std::placeholders::_1); 
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), callback);
                if(!ret)
                {
                    ELOG("回调rpc请求失败！");
                    return false;
                }
                return true;
            }
        private:
            void CallBackSync(JsonResponseCallBack &cb, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg  = std::dynamic_pointer_cast<RPCResponse>(msg);
                if(!rpc_rsp_msg)
                {
                    ELOG("rpc响应，向下类型转换失败");
                    return;
                }
                if(rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    std::string err_msg = errReason(rpc_rsp_msg->rcode());
                    ELOG("rpc请求出错: %s", err_msg.c_str());
                    return;
                }
                cb(rpc_rsp_msg->result());
            }
            void CallBack(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg  = std::dynamic_pointer_cast<RPCResponse>(msg);
                if(!rpc_rsp_msg)
                {
                    ELOG("rpc响应，向下类型转换失败");
                    return;
                }
                if(rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    std::string err_msg = errReason(rpc_rsp_msg->rcode());
                    ELOG("rpc请求出错: %s", err_msg.c_str());
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }
        private:
            Requestor::ptr _requestor;
        };
    }
}